﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

namespace Nirvana
{
   [CustomEditor(typeof(AudioItem))]
    public class AudioItemEditor : Editor
    {
        private SerializedProperty playMode;
        private SerializedProperty subItems;
        private SerializedProperty outputAudioMixerGroup;
        private SerializedProperty volume;
        private SerializedProperty delay;
        private SerializedProperty spatialBlend;
        private SerializedProperty interval;
        private SerializedProperty maxCount;
        private SerializedProperty audioGroup;

        private ReorderableList subitemList;
        private AudioSource audioSource;
        private LinkedList<IBasicAudio> audioPlayers = new LinkedList<IBasicAudio>();

        public override void OnInspectorGUI()
        {
            base.serializedObject.Update();
            this.subitemList.DoLayoutList();
            EditorGUILayout.PropertyField(this.playMode, new GUIContent("Play Mode"));
            EditorGUILayout.PropertyField(this.outputAudioMixerGroup, new GUIContent("Mixer Group"));
            EditorGUILayout.PropertyField(this.volume, new GUIContent("Volume"));
            EditorGUILayout.PropertyField(this.delay, new GUIContent("Delay"));
            EditorGUILayout.PropertyField(this.spatialBlend, new GUIContent("Spatial Blend"));
            EditorGUILayout.PropertyField(this.interval, new GUIContent("Interval"));
            EditorGUILayout.PropertyField(this.maxCount, new GUIContent("Max Count"));
            EditorGUILayout.PropertyField(this.audioGroup, new GUIContent("Audio Group"));

            base.serializedObject.ApplyModifiedProperties();
            if (GUILayout.Button("Play"))
            {
                AudioItem audioItem = (AudioItem)this.target;
                var audioplayer = AudioManager.Play(audioItem);
                if (audioplayer.IsPlaying)
                {
                    LinkedListNode<IBasicAudio> node = this.audioPlayers.AddLast(audioplayer);
                    AudioManager.Instance.StartCoroutine(Remove(audioplayer, node));
                }
            }

            if(this.audioPlayers.Count > 0)
            {
                EditorGUILayout.PrefixLabel("Playing Items:");
                GUILayoutEx.BeginContents();
                foreach(var p in this.audioPlayers)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField(p.ToString());
                    if (GUILayout.Button("Stop")) p.Stop();
                    EditorGUILayout.EndHorizontal();
                }
                GUILayoutEx.EndContents();
            }
        }

        private void OnEnable()
        {
            SerializedObject serializedObject = base.serializedObject;
            this.playMode = serializedObject.FindProperty("playMode");
            this.subItems = serializedObject.FindProperty("subItems");
            this.outputAudioMixerGroup = serializedObject.FindProperty("mixerGroup");
            this.volume = serializedObject.FindProperty("volume");
            this.delay = serializedObject.FindProperty("delay");
            this.spatialBlend = serializedObject.FindProperty("spatialBlend");
            this.interval = serializedObject.FindProperty("interval");
            this.maxCount = serializedObject.FindProperty("maxCount");
            this.audioGroup = serializedObject.FindProperty("audioGroup");

            subitemList = new ReorderableList(serializedObject, this.subItems);
            subitemList.drawHeaderCallback = DrawHeader;
            subitemList.elementHeightCallback = OnElementHeight;
            subitemList.drawElementCallback = DrawElement;
            subitemList.onAddCallback = OnAddCallback;

            AudioItem audioItem = (AudioItem)this.target;
            audioItem.Reset();

            if(this.audioSource == null)
            {
                this.audioSource = new GameObject("Play Audio Sub-Item")
                {
                    hideFlags = HideFlags.HideAndDontSave
                }.AddComponent<AudioSource>();
            }

            UnitySingleton<AudioManager>.CheckInstance();
        }

        private void OnDisable()
        {
            foreach(var p in this.audioPlayers)
            {
                p.Stop();
            }
            this.audioPlayers.Clear();
            if(this.audioSource != null)
            {
                GameObject.DestroyImmediate(this.audioSource.gameObject);
            }
            this.subitemList = null;

        }

        private IEnumerator Remove(IBasicAudio audioPlayer,LinkedListNode<IBasicAudio> node)
        {
            yield return audioPlayer.WaitFinish();
            if (audioPlayers.Count != 0) this.audioPlayers.Remove(node);
            this.Repaint();
            yield break;
        }


        private void DrawHeader(Rect rect)
        {
            GUI.Label(rect, "Sub-Items:");
        }

        private float OnElementHeight(int index)
        {
            return 14f * EditorGUIUtility.singleLineHeight;
        }

        private void DrawElement(Rect r, int index, bool isActive, bool isFocused)
        {
            SerializedProperty arrayElementAtIndex = this.subItems.GetArrayElementAtIndex(index);

            SerializedProperty audioClip = arrayElementAtIndex.FindPropertyRelative("audioClip");
            SerializedProperty outputAudioMixerGroup = arrayElementAtIndex.FindPropertyRelative("mixerGroup");
            SerializedProperty weight = arrayElementAtIndex.FindPropertyRelative("weight");
            SerializedProperty volume = arrayElementAtIndex.FindPropertyRelative("volume");
            SerializedProperty randomVolume = arrayElementAtIndex.FindPropertyRelative("randomVolume");
            SerializedProperty pitch = arrayElementAtIndex.FindPropertyRelative("pitch");
            SerializedProperty randomPitch = arrayElementAtIndex.FindPropertyRelative("randomPitch");
            SerializedProperty delay = arrayElementAtIndex.FindPropertyRelative("delay");
            SerializedProperty randomDelay = arrayElementAtIndex.FindPropertyRelative("randomDelay");
            SerializedProperty startAt = arrayElementAtIndex.FindPropertyRelative("startAt");
            SerializedProperty randomStartAt = arrayElementAtIndex.FindPropertyRelative("randomStartAt");
            SerializedProperty fadeInTime = arrayElementAtIndex.FindPropertyRelative("fadeInTime");
            SerializedProperty fadeOutTime = arrayElementAtIndex.FindPropertyRelative("fadeOutTime");

            Rect rect = new Rect(r.x, r.y, r.width, EditorGUIUtility.singleLineHeight);
            EditorGUI.PropertyField(rect, audioClip, new GUIContent("Audio Clip:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, outputAudioMixerGroup, new GUIContent("Mixer Group:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, weight, new GUIContent("Weight:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, volume, new GUIContent("Volume:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, randomVolume, new GUIContent("Random Volume(+-):"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, pitch, new GUIContent("Pitch:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, randomPitch, new GUIContent("Random Pitch(+-):"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, delay, new GUIContent("Delay:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, randomDelay, new GUIContent("Random Delay(+-):"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, startAt, new GUIContent("Start At:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, randomStartAt, new GUIContent("Random Start At(+-):"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, fadeInTime, new GUIContent("Fade In Time:"));
            rect.y += EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, fadeOutTime, new GUIContent("Fade Out Time:"));
            rect.y += EditorGUIUtility.singleLineHeight;

            if (GUI.Button(rect, "Play"))
            {
                AudioItem audioItem = (AudioItem)this.target;
                audioItem.PlaySubItem(index, this.audioSource);
            }
        }

        private void OnAddCallback(ReorderableList list)
        {
            AudioItem audioItem = (AudioItem)this.target;
            audioItem.InitDefaultSubItem();
            EditorUtility.SetDirty(this.target);
        }



    }
}

